package cn.hejiang.mamis.core.controller;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;

import cn.hejiang.mamis.core.dto.AmisCrudDTO;
import cn.hejiang.mamis.core.dto.OptionDTO;
import cn.hejiang.mamis.core.dto.ResultDTO;
import cn.hejiang.mamis.core.entity.PlatSys;
import cn.hejiang.mamis.core.entity.PlatUser;
import cn.hejiang.mamis.core.entity.SessionDetails;
import cn.hejiang.mamis.core.service.ContextService;
import cn.hejiang.mamis.core.service.PlatSysService;
import cn.hejiang.mamis.core.service.SysApiService;
import cn.hejiang.mamis.core.service.SysMenuService;
import cn.hejiang.mamis.core.service.SysPageService;
import cn.hejiang.mamis.core.service.SysRoleService;
import cn.hejiang.mamis.core.util.EntityUtil;
import cn.hejiang.mamis.core.util.QueryUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;

@RequestMapping("/mamis/plat/sys")
@RestController
@Slf4j
public class PlatSysController {
	@Autowired
	ContextService contextService;

	@Autowired
	PlatSysService platSysService;

	@Autowired
	SysMenuService sysMenuService;

	@Autowired
	SysRoleService sysRoleService;

	@Autowired
	SysPageService sysPageService;

	@Autowired
	SysApiService sysApiService;

	@GetMapping("/list")
	public ResultDTO<AmisCrudDTO<PlatSys>> getSysList(
			@RequestParam(value = "status", required = false) Integer status) {
		// 查询数据库
		List<PlatSys> list = status == null ? platSysService.getSysList() : platSysService.getSysListByStatus(status);

		// 构造 amis 要求的数据结构
		final AmisCrudDTO<PlatSys> data = new AmisCrudDTO<>();
		data.setItems(list);
		// data.setTotal(platSysMapper.selectCount(wrapper));

		// 返回结果集
		return ResultDTO.success(data);
	}

	@PostMapping()
	public ResultDTO<PlatSys> saveSys(final HttpServletRequest request, @RequestBody final PlatSys obj) {
		final SessionDetails session = contextService.getSession(request);

		// 清除不可更新字段
		obj.setDeleted(null);
		obj.setOwnSysId(null);
		obj.setOwnDeptId(null);
		obj.setCreatedAt(null);
		obj.setCreatedBy(null);
		obj.setUpdatedAt(null);
		obj.setUpdatedBy(session.getCurUserId());

		boolean ret;
		if (StrUtil.isNotBlank(obj.getId())) {
			// update
			UpdateWrapper<PlatSys> updater = QueryUtil.newUpdateWrapper(obj.getId());
			ret = platSysService.update(obj, updater);
		} else {
			// 新建系统
			ret = platSysService.createSys(obj, contextService.getSystem().getId(), session.getCurUserId());
		}

		return ret ? ResultDTO.success(obj) : ResultDTO.error("保存失败");
	}

	@GetMapping("/admin")
	public ResultDTO<Map<String, String>> getAdmin(final HttpServletRequest request,
			@RequestParam("sysId") String sysId) {
		List<PlatUser> adminList = platSysService.getSysAdminList(sysId);
		String userPicker;
		if (adminList.size() > 0) {
			userPicker = adminList.stream().map(u -> u.getId()).reduce((s1, s2) -> (s1 + ',' + s2)).get();
		} else {
			userPicker = "";
		}

		Map<String, String> obj = new HashMap<>();
		obj.put("userPicker", userPicker);
		return ResultDTO.success(obj);
	}

	@PostMapping("/admin")
	public ResultDTO setAdmin(final HttpServletRequest request, @RequestParam("sysId") String sysId,
			@RequestBody Map<String, String> body) {
		final SessionDetails session = contextService.getSession(request);

		String[] userIds = body.get("userPicker").split(",");
		int ret = platSysService.setSysAdmins(sysId, userIds, session.getCurUserId());
		return ret > 0 ? ResultDTO.success() : ResultDTO.error("保存失败");
	}

	@DeleteMapping("/{id}")
	public ResultDTO delSys(final HttpServletRequest request, @PathVariable("id") String id) {
		UpdateWrapper<PlatSys> wrapper = QueryUtil.newDeleteWrapper(id);
		boolean ret = platSysService.update(null, wrapper);

		return ret ? ResultDTO.success() : ResultDTO.error("删除失败");
	}

	@GetMapping("/option/list")
	public ResultDTO<List<OptionDTO>> getSysOptionList(
			@RequestParam(value = "status", required = false) Integer status) {
		// 查询数据库
		final List<PlatSys> sysList = status == null ? platSysService.getSysList()
				: platSysService.getSysListByStatus(status);
		final List<OptionDTO> sysOptionList = EntityUtil.toOptionList(sysList);

		// 返回结果集
		return ResultDTO.success(sysOptionList);
	}

	@PostMapping("/export")
	public void export(final HttpServletRequest request, final HttpServletResponse response,
			@RequestParam("ids") String ids) throws IOException {
		// 创建导出根文件夹
		Path rootPath = Files.createTempDirectory("mamis_");
		File rootFolder = rootPath.toFile();

		// 支持多个系统一起导出
		for (String id : ids.split(",")) {
			PlatSys sys = platSysService.getSysById(id);

			// 创建导出系统文件夹
			File sysFolder = new File(rootFolder, id);

			// 创建导出文件
			{
				File metaFile = new File(sysFolder, "meta.json");
				FileUtil.writeBytes(JSONUtil.toJsonStr(sys).getBytes(StandardCharsets.UTF_8), metaFile);
			}

			{
				File menuFile = new File(sysFolder, "menu.json");
				Map<String, Object> menuMap = new HashMap<>();
				menuMap.put("menu", sysMenuService.getMenuList(id));
				FileUtil.writeBytes(JSONUtil.toJsonStr(menuMap).getBytes(StandardCharsets.UTF_8), menuFile);
			}

			{
				File roleFile = new File(sysFolder, "role.json");
				Map<String, Object> roleMap = new HashMap<>();
				roleMap.put("role", sysRoleService.getDeptRoleList(null, id));
				FileUtil.writeBytes(JSONUtil.toJsonStr(roleMap).getBytes(StandardCharsets.UTF_8), roleFile);
			}

			{
				File pageFile = new File(sysFolder, "page.json");
				Map<String, Object> pageMap = new HashMap<>();
				pageMap.put("page", sysPageService.getPageList(null, null, id));
				FileUtil.writeBytes(JSONUtil.toJsonStr(pageMap).getBytes(StandardCharsets.UTF_8), pageFile);
			}

			{
				File apiFile = new File(sysFolder, "api.json");
				Map<String, Object> apiMap = new HashMap<>();
				apiMap.put("api", sysApiService.getApiList(id));
				FileUtil.writeBytes(JSONUtil.toJsonStr(apiMap).getBytes(StandardCharsets.UTF_8), apiFile);
			}

			{
				File dbFile = new File(sysFolder, "db.json");
			}
		}

		// 准备下载
		response.reset();
		response.setContentType("application/octet-stream");
		response.setHeader("Content-Disposition", "attachment; filename=mamis.zip");

		try (OutputStream out = response.getOutputStream()) {
			ZipUtil.zip(out, StandardCharsets.UTF_8, false, null, rootFolder);
		}

		response.setStatus(HttpServletResponse.SC_OK);
	}
}
